﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;

namespace YArchitech.HVAC
{
	public class HeatingCalcTools
	{
		public static double GetDensityByTemperature(double dTemperature)
		{
			double result = 1000.0;
			if (HeatingCalcTools.WaterDensityItem == null)
			{
				return result;
			}
			int num = HeatingCalcTools.WaterDensityItem.Keys.Min();
			int num2 = HeatingCalcTools.WaterDensityItem.Keys.Max();
			if (dTemperature < (double)num)
			{
				result = HeatingCalcTools.WaterDensityItem[num];
			}
			else if (dTemperature > (double)num2)
			{
				result = HeatingCalcTools.WaterDensityItem[num2];
			}
			else
			{
				result = HeatingCalcTools.WaterDensityItem[(int)dTemperature];
			}
			return result;
		}

		public static int CalcPipeDiameter(Pipe pipe, double flow, double temp, HYHeatingSystemOption option)
		{
			int result = 0;
			Dictionary<int, double> pipeMepSize = HeatingCalcTools.GetPipeMepSize(pipe);
			IOrderedEnumerable<int> orderedEnumerable = from d in pipeMepSize.Keys.ToList<int>()
			select d into d
			where (double)d <= option.DNRange.Max && (double)d >= option.DNRange.Min
			orderby d
			select d;
			double num = 10000.0;
			if (orderedEnumerable.Count<int>() < 1)
			{
				return Convert.ToInt32(pipe.Diameter * 304.8);
			}
			foreach (int num2 in orderedEnumerable)
			{
				double num3 = pipeMepSize[num2];
				double velocity = HeatingCalcTools.CalcVelocity(num3, flow);
				double kinematicViscosity = HeatingCalcTools.GetKinematicViscosity(temp);
				double densityByTemperature = HeatingCalcTools.GetDensityByTemperature(temp);
				double λ = HeatingCalcTools.CalcFrictionCoeffic(velocity, num3, 0.2, kinematicViscosity);
				double num4 = HeatingCalcTools.CalcRm(velocity, num3, λ, densityByTemperature);
				if (Math.Abs(num4 - 45.0) <= num)
				{
					result = Convert.ToInt32(num2);
					num = Math.Abs(num4 - 45.0);
				}
			}
			return result;
		}

		public static double CalcFlowByLoad(double load, double tempSupply, double tempBack)
		{
			return 0.86 * load * 1000.0 / Math.Abs(tempSupply - tempBack);
		}

		public static Dictionary<int, double> GetPipeMepSize(Pipe pipe)
		{
			RoutingPreferenceManager routingPreferenceManager = pipe.PipeType.RoutingPreferenceManager;
			return (pipe.Document.GetElement(routingPreferenceManager.GetRule((Autodesk.Revit.DB.RoutingPreferenceRuleGroupType)0, 0).MEPPartId) as PipeSegment).GetSizes().ToDictionary((MEPSize size) => Convert.ToInt32(size.NominalDiameter * 304.8), (MEPSize size) => size.InnerDiameter * 304.8);
		}

		public static double CalcVelocity(double innerDia, double flow)
		{
			double result = 0.0;
			if (Math.Abs(flow) < 1E-06 || innerDia == 0.0)
			{
				return result;
			}
			double num = innerDia * Math.Pow(10.0, -3.0);
			return flow / (2827.4333882308138 * num * num);
		}

		public static double CalcFrictionCoeffic(double velocity, double innerDiameter, double K, double KViscosity)
		{
			double num = 0.0;
			if (Math.Abs(velocity) < 1E-06 || innerDiameter == 0.0)
			{
				return num;
			}
			double num2 = K / innerDiameter;
			double num3 = velocity * innerDiameter * Math.Pow(10.0, -3.0) / (KViscosity * Math.Pow(10.0, -6.0));
			if (num3 <= 2320.0)
			{
				num = 64.0 / num3;
			}
			else
			{
				num = 0.1;
				int num4 = 0;
				double num5 = 0.1;
				while (num5 > Math.Pow(10.0, -6.0) && num4 <= 10)
				{
					double num6 = 2.51 / (num3 * Math.Sqrt(num)) + num2 / 3.72;
					num6 = -2.0 * Math.Log10(num6);
					double num7 = 1.0 / (num6 * num6);
					num5 = Math.Abs(num7 - num);
					num = num7;
					num4++;
				}
			}
			return num;
		}

		public static double CalcRm(double velocity, double innerDiameter, double λ, double density)
		{
			double result = 0.0;
			if (Math.Abs(velocity) < 1E-06 || innerDiameter == 0.0)
			{
				return result;
			}
			innerDiameter *= Math.Pow(10.0, -3.0);
			return 0.5 * (λ * density * velocity * velocity) / innerDiameter;
		}

		public static double GetKinematicViscosity(double temperature)
		{
			int[] array = new int[]
			{
				0,
				5,
				10,
				15,
				20,
				30,
				40,
				60,
				80
			};
			double[] array2 = new double[]
			{
				1.792,
				1.52,
				1.307,
				1.139,
				1.004,
				0.801,
				0.658,
				0.475,
				0.365
			};
			int num = Convert.ToInt32(temperature + 0.5);
			if (num >= 80)
			{
				return array2.Last<double>();
			}
			double result = array2[0];
			for (int i = 0; i < 9; i++)
			{
				if (num < array[i])
				{
					double num2 = array2[i - 1] + (array2[i] - array2[i - 1]);
					double num3 = (double)(array[i] - array[i - 1]);
					result = num2 * (double)(num - array[i - 1]) / num3;
				}
			}
			return result;
		}

		public static double GetResCoefLocal(ValveAndFittingType type, int dn)
		{
			double result = 0.0;
			switch (type)
			{
			case ValveAndFittingType.Gate:
				if (dn >= 20)
				{
					result = 0.5;
				}
				else
				{
					result = 1.5;
				}
				break;
			case ValveAndFittingType.Stop:
				if (dn >= 50)
				{
					result = 7.0;
				}
				else if (dn >= 40)
				{
					result = 8.0;
				}
				else if (dn >= 25)
				{
					result = 9.0;
				}
				else if (dn >= 20)
				{
					result = 10.0;
				}
				else
				{
					result = 16.0;
				}
				break;
			case ValveAndFittingType.RodStop:
				if (dn >= 50)
				{
					result = 2.0;
				}
				else if (dn >= 32)
				{
					result = 2.5;
				}
				else
				{
					result = 3.0;
				}
				break;
			case ValveAndFittingType.Elbow:
				if (dn >= 40)
				{
					result = 1.5;
				}
				else if (dn >= 25)
				{
					result = 1.5;
				}
				else
				{
					result = 2.0;
				}
				break;
			case ValveAndFittingType.Bend:
				if (dn >= 40)
				{
					result = 0.5;
				}
				else if (dn >= 25)
				{
					result = 1.0;
				}
				else
				{
					result = 1.5;
				}
				break;
			case ValveAndFittingType.Expansion:
				if (dn >= 20)
				{
					result = 2.0;
				}
				else
				{
					result = 3.0;
				}
				break;
			case ValveAndFittingType.Square:
				result = 2.0;
				break;
			case ValveAndFittingType.Casing:
				result = 0.5;
				break;
			case ValveAndFittingType.DirectTee:
				result = 1.0;
				break;
			case ValveAndFittingType.SideTee:
				result = 1.5;
				break;
			case ValveAndFittingType.ShuntTee:
				result = 3.0;
				break;
			case ValveAndFittingType.TogetherTee:
				result = 3.0;
				break;
			case ValveAndFittingType.DirectCross:
				result = 2.0;
				break;
			case ValveAndFittingType.STCorss:
				result = 3.0;
				break;
			case ValveAndFittingType.Other:
				result = 0.0;
				break;
			case ValveAndFittingType.Expand:
				result = 1.0;
				break;
			case ValveAndFittingType.Narrow:
				result = 0.5;
				break;
			}
			return result;
		}

		private const double K = 0.2;

		private const double AverageRm = 45.0;

		private const double ERROR6 = 1E-06;

		private static readonly Dictionary<int, double> WaterDensityItem = new Dictionary<int, double>
		{
			{
				0,
				999.9
			},
			{
				1,
				999.9
			},
			{
				2,
				1000.0
			},
			{
				3,
				1000.0
			},
			{
				4,
				1000.0
			},
			{
				5,
				1000.0
			},
			{
				6,
				1000.0
			},
			{
				7,
				999.95
			},
			{
				8,
				999.9
			},
			{
				9,
				999.8
			},
			{
				10,
				999.7
			},
			{
				11,
				999.58
			},
			{
				12,
				999.46
			},
			{
				13,
				999.34
			},
			{
				14,
				999.22
			},
			{
				15,
				999.1
			},
			{
				16,
				998.92
			},
			{
				17,
				998.74
			},
			{
				18,
				998.56
			},
			{
				19,
				998.38
			},
			{
				20,
				998.2
			},
			{
				21,
				997.98
			},
			{
				22,
				997.76
			},
			{
				23,
				997.54
			},
			{
				24,
				997.32
			},
			{
				25,
				997.1
			},
			{
				26,
				996.82
			},
			{
				27,
				996.54
			},
			{
				28,
				996.26
			},
			{
				29,
				995.98
			},
			{
				30,
				995.7
			},
			{
				31,
				995.38
			},
			{
				32,
				995.06
			},
			{
				33,
				994.74
			},
			{
				34,
				994.42
			},
			{
				35,
				994.1
			},
			{
				36,
				993.73
			},
			{
				37,
				993.36
			},
			{
				38,
				992.98
			},
			{
				39,
				992.61
			},
			{
				40,
				992.24
			},
			{
				41,
				991.84
			},
			{
				42,
				991.44
			},
			{
				43,
				991.05
			},
			{
				44,
				990.65
			},
			{
				45,
				990.25
			},
			{
				46,
				989.81
			},
			{
				47,
				989.38
			},
			{
				48,
				988.94
			},
			{
				49,
				988.51
			},
			{
				50,
				988.07
			},
			{
				51,
				987.6
			},
			{
				52,
				987.13
			},
			{
				53,
				986.67
			},
			{
				54,
				986.2
			},
			{
				55,
				985.73
			},
			{
				56,
				985.24
			},
			{
				57,
				984.75
			},
			{
				58,
				984.26
			},
			{
				59,
				983.77
			},
			{
				60,
				983.28
			},
			{
				61,
				982.75
			},
			{
				62,
				982.22
			},
			{
				63,
				981.69
			},
			{
				64,
				981.16
			},
			{
				65,
				980.63
			},
			{
				66,
				980.08
			},
			{
				67,
				979.54
			},
			{
				68,
				978.99
			},
			{
				69,
				978.45
			},
			{
				70,
				977.9
			},
			{
				71,
				977.29
			},
			{
				72,
				976.68
			},
			{
				73,
				976.07
			},
			{
				74,
				975.46
			},
			{
				75,
				974.85
			},
			{
				76,
				974.25
			},
			{
				77,
				973.65
			},
			{
				78,
				973.04
			},
			{
				79,
				972.44
			},
			{
				80,
				971.84
			},
			{
				81,
				971.19
			},
			{
				82,
				970.53
			},
			{
				83,
				969.88
			},
			{
				84,
				969.22
			},
			{
				85,
				968.57
			},
			{
				86,
				967.92
			},
			{
				87,
				967.28
			},
			{
				88,
				966.63
			},
			{
				89,
				965.99
			},
			{
				90,
				965.34
			},
			{
				91,
				964.64
			},
			{
				92,
				963.93
			},
			{
				93,
				963.23
			},
			{
				94,
				962.52
			},
			{
				95,
				961.82
			},
			{
				96,
				961.13
			},
			{
				97,
				960.45
			},
			{
				98,
				959.77
			},
			{
				99,
				959.08
			},
			{
				100,
				958.4
			}
		};
	}
}
